using System;
using System.Collections.Generic;
using System.Text;
using Sixeyed.CodeGeneration.Metadata.Interfaces;
using SqlServer = Sixeyed.CodeGeneration.Metadata.Database.Sources;

namespace Sixeyed.CodeGeneration.Metadata
{
    /// <summary>
    /// Container for metadata sources
    /// </summary>
    public static class SourceContainer
    {
        #region Static fields

        private static SourceAssemblyConfiguration sourceAssemblyConfiguration;
        private static Dictionary<string, IMetadataSource> sources;
        private static bool loaded;

        #endregion

        #region Static properties

        /// <summary>
        /// Gets whether the container has loaded any sources
        /// </summary>
        public static bool Loaded
        {
            get { return loaded; }
        }

        /// <summary>
        /// Gets/sets assembly configuration for metadata sources
        /// </summary>
        public static SourceAssemblyConfiguration SourceAssemblyConfiguration
        {
            get 
            {
                if (sourceAssemblyConfiguration == null)
                {
                    sourceAssemblyConfiguration = new SourceAssemblyConfiguration();
                    Load();
                }
                return sourceAssemblyConfiguration; 
            }
            set
            {
                sourceAssemblyConfiguration = value;
                Load();
            }
        }

        /// <summary>
        /// Gets the collection of metadata sources
        /// </summary>
        public static Dictionary<string, IMetadataSource> Sources
        {
            get
            {
                if (sources == null)
                {
                    sources = new Dictionary<string, IMetadataSource>();
                }
                return sources;
            }
        }

        #endregion

        #region Static methods

        /// <summary>
        /// Loads configured sources to the collection
        /// </summary>
        private static void Load()
        {
            foreach (IMetadataSource source in SourceAssemblyConfiguration.GetSources())
            {
                AddSource(source);
            }
        }

        /// <summary>
        /// Adds a metadata source ot the collection
        /// </summary>
        /// <param name="source">Metadata source to add</param>
        public static void AddSource(IMetadataSource source)
        {
            if (!Sources.ContainsKey(source.Name))
            {
                Sources.Add(source.Name, source);
            }
            loaded = true;
        }

        /// <summary>
        /// Returns a list of known source types
        /// </summary>
        /// <returns>Source type name list</returns>
        public static List<string> GetSourceTypeNames()
        {
            List<string> typeNames = new List<string>(Sources.Count);
            foreach (IMetadataSource source in Sources.Values)
            {
                if (!typeNames.Contains(source.SourceTypeName))
                {
                    typeNames.Add(source.SourceTypeName);
                }
            }
            return typeNames;
        }

        /// <summary>
        /// Returns a list of metadata sources
        /// </summary>
        /// <returns>Source name list</returns>
        public static List<string> GetSourceNames()
        {
            List<string> keys = new List<string>(Sources.Count);
            keys.AddRange(Sources.Keys);
            return keys;
        }

        /// <summary>
        /// Returns a list of metadata sources of the given type
        /// </summary>
        /// <param name="sourceTypeName">Source type to list</param>
        /// <returns>Source name list</returns>
        public static List<string> GetSourceNames(string sourceTypeName)
        {
            List<string> sources = new List<string>(Sources.Count);
            foreach (IMetadataSource source in Sources.Values)
            {
                if (source.SourceTypeName == sourceTypeName)
                {
                    sources.Add(source.Name);
                }
            }
            return sources;
        }

        /// <summary>
        /// Returns a list of metadata sources of the given type
        /// </summary>
        /// <param name="sourceTypeName">Source type to list</param>
        /// <returns>Source list</returns>
        public static List<IMetadataSource> GetSources(string sourceTypeName)
        {
            List<IMetadataSource> sources = new List<IMetadataSource>(Sources.Count);
            foreach (IMetadataSource source in Sources.Values)
            {
                if (source.SourceTypeName == sourceTypeName)
                {
                    sources.Add(source);
                }
            }
            return sources;
        }

        /// <summary>
        /// Returns the metadata source with the given name
        /// </summary>
        /// <param name="sourceName">Source name</param>
        /// <returns>Source</returns>
        public static IMetadataSource GetSource(string sourceName)
        {
            return Sources[sourceName];
        }

        #endregion
    }
}
